/*
  ID: nemokin1
  PROG: castle
  LANG: C++
*/

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <fstream>
 
using namespace std;
 
#define REP(i,n) for(int i=0; i<(n); ++i)
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define FORD(i,a,b) for(int i=(a);i>=b;--i)
#define FOREACH(it,c) for(typeof((c).begin()) it=(c).begin();it!=(c).end();++it)
#define ALL(c) (c).begin(),(c).end()
 
#define debug(x) cerr<< #x << " = " << (x) << "\n";
#define debugv(v) cerr << #v << " = "; FOREACH(it,v) cerr << *it <<","; cerr << "\n";
#define SIZE(a)  (int(a.size()))
 
template<typename T> inline void checkMax(T& a, T b) {if (b>a) a=b;}
template<typename T> inline void checkMin(T& a, T b) {if (b<a) a=b;}
 
typedef long long LL;
typedef vector<int> VI;
typedef vector<string> VS;
typedef long double ld;
const int INF = 1000000000;

int graph[51][51];
int visited[51][51];

int dy[] = {-1,0,1,0};
int dx[] = {0,-1,0,1};		// west,north,east,south

int maxsize = 0;

int M,N;

bool check(int num, int direction)
{
    if((1<<direction) & num) return false;
    return true;
}

void dfs(int i,int j, int &size, int color)
{
    //cout<<"("<<i<<","<<j<<")";
    visited[i][j] = color;
    for(int r = 0; r < 4; r++){
	if(check(graph[i][j],r) == false) continue;	
	int x = i+dx[r];
	int y = j+dy[r];
	if(x>=M||x<0||y>=N||y<0) continue;
	if(visited[x][y]) continue;
	size++;
	dfs(x,y,size,color);
    }
}
int house[3000];

int colorit()
{
    memset(visited,0,sizeof(visited));
    int color = 1;
    REP(i,M)REP(j,N){
	if(!visited[i][j]) {
	    int size = 1;
	    dfs(i,j,size,color);
	    house[color-1] = size;
	    color++;
	}
    }
    return color-1;
}

int main() {
    freopen("castle.in","r",stdin);freopen("castle.out","w",stdout);
    cin >> N >> M;
    REP(i,M) REP(j,N){
	int num;
	cin >> num;
	graph[i][j] = num;
    }

    int roomNum;
    int roomSize = 0;
    
    roomNum = colorit();
    cout<<roomNum<<endl;
    for(int i = 0; i < roomNum; i++)
	checkMax(roomSize,house[i]);
    cout<<roomSize<<endl;
    
    int max_ret = 0;
    vector<pair<pair<int, int> ,int> > rr;

    for(int i = 0; i < M; i++){
	for(int j = 0; j < N; j++){
	    for(int k = 0; k < 4; k++){
		int x = i+dx[k];
		int y = j+dy[k];
		if(x<0||x>=M||y<0||y>=N) continue;
		if(visited[i][j] == visited[x][y]) continue;
		int sq = house[visited[i][j]-1]+house[visited[x][y]-1];
		if(sq > max_ret){
		    rr.clear();
		    max_ret = sq;
		    rr.push_back(make_pair(make_pair(j,-i),k));
		    int sd;
		    if(k==0) sd = 2;
		    if(k==2) sd = 0;
		    if(k==1) sd = 3;
		    if(k==3) sd = 1;
		    rr.push_back(make_pair(make_pair(y,-x),sd));		    
		}
		if(sq == max_ret){
		    rr.push_back(make_pair(make_pair(j,-i),k));
		    int sd;
		    if(k==0) sd = 2;
		    if(k==2) sd = 0;
		    if(k==1) sd = 3;
		    if(k==3) sd = 1;
		    rr.push_back(make_pair(make_pair(y,-x),sd));		    

		}
	    }
	}
    }
    
    
    cout<<max_ret<<endl;
    sort(ALL(rr));

    cout<<-rr[0].first.second+1<<" "\
	<<rr[0].first.first+1<<" ";
    int dr = rr[0].second;
    switch(dr){
    case 0: cout<<"W"<<endl;
	break;
    case 1: cout<<"N"<<endl;
	break;
    case 2: cout<<"E"<<endl;
	break;
    case 3: cout<<"S"<<endl;
	break;
    }
    exit(0);
}
